package pt.inescid.components.policyengine.heimdall.pdp.base;

import pt.inescid.components.policyengine.heimdall.pap.base.CesAggDefinition;
import pt.inescid.components.policyengine.heimdall.pap.base.CompositeDefinition;
import pt.inescid.components.policyengine.heimdall.pap.base.EventFieldDefinition;
import pt.inescid.components.policyengine.heimdall.pap.base.ExternalMethodDefinition;
import pt.inescid.components.policyengine.heimdall.pap.base.RuleDefinition;
import pt.inescid.components.policyengine.heimdall.pap.base.SimpleDefinition;
import pt.inescid.components.policyengine.heimdall.pap.base.SubPolicyDefinition;
import pt.inescid.components.policyengine.heimdall.pdp.PolicyDecision;

public abstract class RuleInstance {

//  ----------------------------------------------------------
//  ------------------------   INSTANCE variables   ------------------------
//  ----------------------------------------------------------
	protected RuleDefinition definition;
	protected PolicyDecision decision;



//  ----------------------------------------------------------
//  ------------------------   constructor   ------------------------
//  ----------------------------------------------------------
	public RuleInstance(RuleDefinition definition) {
		this.definition = definition;
		decision = new PolicyDecision();
	}
	

	public static RuleInstance getInstance(RuleDefinition definition, 
			ModelInstance currentModel,
			PolicyInstance currentPolicy) {
		RuleInstance ri = null;
		if (definition == null) {
			return (null);
		}
		else if (definition.isCompositeExpression()) {
			ri = (RuleInstance)(new CompositeInstance((CompositeDefinition) definition,
					currentModel, currentPolicy));									
			return ri;
		}
		else if (definition.getType() == RuleDefinition.LITERAL_EXPRESSION) {
			return (new SimpleInstance((SimpleDefinition) definition, currentPolicy));
		}
		else if (definition.getType() == RuleDefinition.SUBPOLICY_EXPRESSION) {
			return (new SubPolicyInstance((SubPolicyDefinition) definition,
					currentModel, currentPolicy));
		}
		else if (definition.getType() == RuleDefinition.EVENT_FIELD_EXPRESSION) {
			return (new EventFieldInstance((EventFieldDefinition) definition,
					currentModel, currentPolicy));
		}
		else if (definition.getType() == RuleDefinition.CES_SUM_EXPRESSION) {
			return (new CesAggInstance((CesAggDefinition) definition,
					currentModel, currentPolicy));
		}
		else if (definition.getType() == RuleDefinition.EXTERNAL_METHOD_EXPRESSION) {
			return (new ExternalMethodInstance(
					(ExternalMethodDefinition) definition,
					currentModel, currentPolicy));
		}
		
		System.out.println("Tipo de regra desconhecido: " + 
				definition.getType());
		System.exit(-1);
		return (null);
	}


	public PolicyDecision getDecision() {
		return decision;
	}


	public RuleDefinition getDefinition() {
		return definition;
	}

//  ----------------------------------------------------------
//  ------------------------   removeCeDependence   ------------------------
//  ----------------------------------------------------------
//	public void removeCeDependence() {
//	}

//  ----------------------------------------------------------
//  ------------------------   toString   ------------------------
//  ----------------------------------------------------------
	public String toString() {
		String result = "";
		
		result += "Rule " + definition.getFunction() + "\n";
		result += "\tDecis:\n" + decision + "\n";
		
		return (result);
	}


	public void resetEvaluation(ModelInstance currentModel) {
	}

	
//  ----------------------------------------------------------
//  ------------------------   abstract methods   ------------------------
//  ----------------------------------------------------------
	public abstract Object evaluate(ModelInstance currentModel,
			boolean onlyCached);


	public void setDecision(PolicyDecision decision) {
		this.decision = decision;
	}
	


}; // RuleInstance
